/*******************************************************************/
/* @ All Rights Reserved Copyright (C) 2014 broada,Co.,Ltd.        */
/*                                                                 */
/*  NAME      = frreport_mng.h                                     */
/*  NOTE      = 上报数据模块                                       */
/*  DATE      = 2014/11/20                                         */
/*******************************************************************/

#ifndef __FRREPORT_MNG_H_
#define __FRREPORT_MNG_H_

#include "frcomm.h"
#include "frlist.h"

#include "conntrack.h"

//保存l7data的连表
#define APM_REPORT_TYPE_L7DATA     0   //l7data数据连表
#define APM_REPORT_TYPE_OTHER      1   //其他能单独上报数据

//连接跟踪
typedef struct __st_report_conn {
    char arr_connection_id[APM_UUID_SIZE];

    u_short ip_proto;             /* 6(IPPROTO_TCP) / 17(IPPROTO_UDP) */
    char src_mac[APM_MAC_SIZE];   /* src mac */
    u_int src_ip;
    u_short src_port;
    u_int dst_ip;
    u_short dst_port;

    /*
        CONNECTING = 1;  //TCP syn包发出后发送connecting消息
        ESTABLISHED = 2; //TCP三次握手后或UDP连接建立时发送established消息
        DISCONNECT = 3; //TCP收到fin包后发送disconnect消息
        DESTROY = 4; //连接被强制销毁时发送destroy消息
        DATA_TIMEOUT = 5; //连接30分钟内未没有任何数据包时发送data_timeout消息
    */
    int i_event;                    /* enum ConntrackEvent */
    struct timeval st_timestamp;    /* 发生时间 */

} Frreport_conn;

//关联链路信息
typedef struct __st_report_conn_expect {
    //重定向前的L4层信息
    u_short ip_proto;             /* 6(IPPROTO_TCP) / 17(IPPROTO_UDP) */
    char src_mac[APM_MAC_SIZE];   /* src mac */
    u_int src_ip;
    u_short src_port;
    u_int dst_ip;
    u_short dst_port;

    //重定向信息
    u_int   redirect_ip;    /* 重定向的目标IP */
    u_short redirect_port;  /* 重定向的目标端口 */

    struct timeval st_timestamp;    /* 发生时间 */

} Frreport_conn_expect;

//Session
typedef struct __st_report_session {
    char arr_session_id[APM_UUID_SIZE];
    char arr_connection_id[APM_UUID_SIZE];

    u_short ip_proto;             /* 6(IPPROTO_TCP) / 17(IPPROTO_UDP) */
    char src_mac[APM_MAC_SIZE];   /* src mac */
    u_int src_ip;
    u_short src_port;
    u_int dst_ip;
    u_short dst_port;

    char *p_username;                       //登录用户名
    int i_status;                           //用户登录,用户退出,...
    struct timeval st_timestamp;            //发生时间
    Frlist_header *p_st_lst_session_data;   //session_data(FRdata_field)
} Frreport_session;

typedef struct __st_l7data_field {
    int i_l7_proto;                             /* L7层协议 */
    char *p_module_name;                        /* L7层协议名 */

    long  l_response_code;                      /* 应答的状态码，存放数值  */
    char *p_response_codestring;                /* 应答的状态码串，如HTTP的 200 OK */
    char *p_transaction_title;                  /* 标识符。NULL表示没有 */
    char *p_server_name;                        /* 检查到的服务器名称，如Apache 2.0 */
    int  i_batch_count;                         /* 批处理长度，默认为1(request里使用) */
    char *p_xml_fields;                         /* XML输出结果，如果传统的KV结构无法表述时可选用XML表达，按XML规范存储 */

    //FRdata_field  *p_st_pk_field;               /* 唯一标识字段，例如URL、SQL等 */
    Frlist_header *p_st_lst_request_data;       /* 请求的所有参数列表，字段名双方约定 (FRdata_field) */
    Frlist_header *p_st_lst_response_data;      /* 应答结果列表，字段名双方约定(FRdata_field) */

}FRl7data_field;

//L7 Data
typedef struct __st_report_l7data {
    char arr_session_id[APM_UUID_SIZE];
    char arr_connection_id[APM_UUID_SIZE];

    u_short ip_proto;                           /* 6(IPPROTO_TCP) / 17(IPPROTO_UDP) */
    char src_mac[APM_MAC_SIZE];                 /* src mac */
    u_int src_ip;
    u_short src_port;
    u_int dst_ip;
    u_short dst_port;

    int i_use_request;                          /* FR_YES 使用该数据 */
    struct timeval st_request_time;             /* 所有请求数据发送完的时间 */
    long   l_request_bytes;                     /* 请求字节数，in bytes */

    char *p_transaction_code;                   /* 交易码，一般从request中提取。NULL表示没有 */
    char *p_transaction_title;                  /* 标识符。NULL表示没有 */
    int i_response_required;                    /* 0:不期待响应数据,1:有response数据 */

    int i_use_response;                         /* FR_YES 使用该数据,如果该值为FR_NO,则为request,否则是response */
    long  l_response_code;                      /* 应答的状态码，存放数值  */
    char *p_response_codestring;                /* 应答的状态码串，如HTTP的 200 OK */

    struct timeval st_response_time_first_byte; /* 收到第一个应答包时间 */
    struct timeval st_response_time;            /* 所有应答包数据接收完的时间 */
    long  l_response_bytes;                     /* 应答的字节数， in bytes */

    unsigned long ul_response_time_firstbyte_us;//首包时间，是指从请求发起到收到第一个应答包时间，使用微秒表示
    unsigned long ul_response_time_us;          //应答时间，是指从请求发起到所有应答结束总花费的时间，使用微秒表示

    Frlist_header st_lst_l7data;                /* response_data(FRl7data_field) */
} Frreport_l7data;

typedef enum __em_report_type
{
    FRREPORT_TYPE_CONN = 1,
    FRREPORT_TYPE_CONN_EXPECT,
    FRREPORT_TYPE_SESSION,
    FRREPORT_TYPE_DATA,
    FRREPORT_TYPE_UNKNOWN,
}Frreport_type;

typedef struct __st_report_data {
    Frreport_type em_data_type;
    union
    {
        Frreport_conn    st_conn;
        Frreport_conn_expect st_conn_expect;
        Frreport_session st_session;
        Frreport_l7data  st_l7data;
    } un_data;

} Frreport_data;

int  frreport_mng_conn_init(void);
void frreport_mng_conn_destory(void);

void frreport_mng_send_report_data(Frreport_data *p_st_report_data);
void frreport_mng_send_conn(Conntrack *p_st_ct, int i_status, struct timeval st_timeval);

void frreport_free_report_data(Frreport_data *p_st_report_data);

#endif
